#pragma once
#include "HPSocket.h"
#include "ELuna.h"

using namespace ELuna;

class hpclient :
	public CUdpCastListener ,
	public CTcpClientListener
{
public:
	hpclient(void* cs,lua_State* L);
	~hpclient(void);
	//TCP
	void			Create_TcpClient();
	//PULL
	void			Create_TcpPullClient();
	int				Fetch				(DWORD pData, int iLength);
	//EnFetchResult Peek	(BYTE* pData, int iLength)
	//PACK
	BOOL			SendPack			(LuaString Data);
	void			Create_TcpPackClient();
	void			SetMaxPackSize		(DWORD dwMaxPackSize);
	void			SetPackHeaderFlag	(USHORT usPackHeaderFlag);
	DWORD			GetMaxPackSize		();
	USHORT			GetPackHeaderFlag	();
	//UDPCAST
	void			Create_UdpCast		();
	void			SetMaxDatagramSize	(DWORD dwMaxDatagramSize);
	DWORD			GetMaxDatagramSize	();
	void			SetReuseAddress		(BOOL bReuseAddress);
	BOOL			IsReuseAddress		()	;
	void			SetCastMode			(int enCastMode);
	int				GetCastMode			()	;
	void			SetMultiCastTtl		(int iMCTtl)	;
	int				GetMultiCastTtl		();
	void			SetMultiCastLoop	(BOOL bMCLoop);
	BOOL			IsMultiCastLoop		();
	USHORT			GetRemoteAddress	(lua_State* L);

	//ITcpClient
	//BOOL SendSmallFile	(LPCTSTR lpszFileName, const LPWSABUF pHead = nullptr, const LPWSABUF pTail = nullptr)
	//BOOL SetupSSLContext	(int iVerifyMode = SSL_VM_NONE, LPCTSTR lpszPemCertFile = nullptr, LPCTSTR lpszPemKeyFile = nullptr, LPCTSTR lpszKeyPasswod = nullptr, LPCTSTR lpszCAPemCertFileOrPath = nullptr)	= 0;
	//void CleanupSSLContext	()		
	void			SetSocketBufferSize		(DWORD dwSocketBufferSize);
	void			SetKeepAliveTime		(DWORD dwKeepAliveTime);
	void			SetKeepAliveInterval	(DWORD dwKeepAliveInterval);
	DWORD			GetSocketBufferSize		();
	DWORD			GetKeepAliveTime		();
	DWORD			GetKeepAliveInterval	();
	//IClient
	BOOL			Start	(const char* pszRemoteAddress, USHORT usPort, BOOL bAsyncConnect,const char* lpszBindAddress);
	BOOL			Stop	();
	BOOL			Send	(DWORD pBuffer, int iLength, int iOffset);
	//BOOL SendPackets(const WSABUF pBuffers[], int iCount)
	//BOOL PauseReceive(BOOL bPause = TRUE)
	//void SetExtra					(PVOID pExtra)
	//PVOID GetExtra					()
	//BOOL IsSecure
	BOOL			HasStarted		();
	int				GetState		();
	int				GetLastError	();
	const char*		GetLastErrorDesc();
	DWORD			GetConnectionID	();
	USHORT			GetLocalAddress	(lua_State* L);
	//BOOL GetRemoteHost			(TCHAR lpszHost[], int& iHostLen, USHORT& usPort)
	int				GetPendingDataLength		();
	//BOOL IsPauseReceive			(BOOL& bPaused)
	//BOOL IsConnected			()
	void			SetFreeBufferPoolSize		(DWORD dwFreeBufferPoolSize);
	void			SetFreeBufferPoolHold		(DWORD dwFreeBufferPoolHold);
	DWORD			GetFreeBufferPoolSize		();
	DWORD			GetFreeBufferPoolHold		();

private:
	virtual EnHandleResult OnPrepareConnect(ITcpClient* pSender, CONNID dwConnID, SOCKET socket);
	virtual EnHandleResult OnConnect	(ITcpClient* pSender, CONNID dwConnID);

	virtual EnHandleResult OnReceive	(ITcpClient* pSender, CONNID dwConnID, int iLength);//PULL
	virtual EnHandleResult OnReceive	(ITcpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength);//PACK,PUSH
	virtual EnHandleResult OnSend		(ITcpClient* pSender, CONNID dwConnID, const BYTE* pData, int iLength);
	virtual EnHandleResult OnClose		(ITcpClient* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode);

	virtual EnHandleResult OnPrepareConnect(IUdpCast* pSender, CONNID dwConnID, SOCKET socket);
	virtual EnHandleResult OnConnect(IUdpCast* pSender, CONNID dwConnID);
	virtual EnHandleResult OnReceive(IUdpCast* pSender, CONNID dwConnID, const BYTE* pData, int iLength);
	virtual EnHandleResult OnSend(IUdpCast* pSender, CONNID dwConnID, const BYTE* pData, int iLength);
	virtual EnHandleResult OnClose(IUdpCast* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode);
private:
	ITcpPullClient* m_pull;
	ITcpPackClient* m_pack;
	IUdpCast*		m_udp;
	ITcpClient*		m_itc;
	IClient*		m_ic;
	int				m_ref;
	lua_State *		m_L;
	LPCRITICAL_SECTION m_cs;
};
int REG_HPClient(lua_State * L);
